unit uMatrix;

interface
uses
  Classes ;

type
  TMatrix = class
  private

    matrix  : array of array of Double ;
    FRow,
    FCol    : Integer ;

    function GetCell ( i , j : Integer ) : Double ;
    procedure WriteCell ( i, j : Integer ; value : Double ) ;

  public

    property Cell [ i , j : Integer] : Double read GetCell write  WriteCell; default ;

    property RowCount : Integer read FRow ;
    property ColCount : Integer read FCol ;

    procedure SetSize ( Row , Col : Integer );

    constructor Create ( ) ; overload ;
    constructor Create ( Row , Col : Integer ) ; overload ;

    procedure RandomizeMatrix (LowBound, HighBound : Double; Signal : Boolean = True);

    procedure Sum (M : TMatrix);
    procedure Multiply(f : Double);

    procedure Clear;

  end;

  TMyMatrixOperations = class
  private


  public
    class function KronMatrix     ( M1 , M2 : TMatrix ) : TMatrix ;
    class function MultiplyMatrix ( M1 , M2 : TMatrix ) : TMatrix ;
    class function TransposeMatrix ( M1 : TMatrix ) : TMatrix ;
    class function CreateM (o : TMatrix) : TMatrix;
  end;


implementation

uses Math;

{ TMatrix }



constructor TMatrix.Create;
begin
  //
end;

procedure TMatrix.Clear;
var
  i ,j : Integer ;
begin

  for i := 0 to FRow - 1 do
  begin
    for j := 0 to FCol - 1 do
    begin
      matrix[i][j] := 0.0 ;
    end;
  end;
end;

constructor TMatrix.Create(Row, Col: Integer);
begin
  Create ();
  SetSize ( Row , Col );
end;

function TMatrix.GetCell(i, j: Integer): Double;
begin
  Result := matrix[i][j] ;
end;

procedure TMatrix.RandomizeMatrix(LowBound, HighBound: Double; Signal: Boolean);
var
  i, j : Integer;
  RandValue : Double;
begin

  for i := 0 to FRow-1 do
    begin
      for j := 0 to FCol-1 do
        begin
          RandValue := Random*(HighBound - LowBound) + LowBound;

          if (Signal) then
            begin
              if (Random > 0.5) then
                begin
                  RandValue := RandValue*(-1);
                end;
            end;
          WriteCell(i, j, RandValue);
        end;
    end;

end;

procedure TMatrix.SetSize(Row, Col: Integer);
var
  i ,j : Integer ;
begin

  SetLength ( matrix , Row , Col ) ;
  FRow  := Row ;
  FCol  := Col ;

  for i := 0 to FRow - 1 do
  begin
    for j := 0 to FCol - 1 do
    begin
      matrix[i][j] := 0.0 ;
    end;
  end;

end;

procedure TMatrix.Sum(M: TMatrix);
var
  i, j : Integer;
begin

  for i := 0 to FRow - 1 do
  begin
    for j := 0 to FCol - 1 do
    begin
      matrix[i][j] := matrix[i][j] + M[i, j] ;
    end;
  end;
end;

procedure TMatrix.WriteCell(i, j: Integer; value: Double);
begin
  matrix[i][j] := value ;
end;

procedure TMatrix.Multiply(f: Double);
var
  i, j : Integer;
begin

  for i := 0 to FRow - 1 do
  begin
    for j := 0 to FCol - 1 do
    begin
      matrix[i][j] := matrix[i][j]*f ;
    end;
  end;
end;

{ TMyMatrixOperations }

class function TMyMatrixOperations.CreateM(o: TMatrix): TMatrix;
var
  i, j : Integer;
begin

  Result := TMatrix.Create(o.RowCount, o.RowCount);
  for i := 0 to o.RowCount-1 do
    begin
      for j := 0 to o.RowCount-1 do
        begin
          if (i = j) then
            Result[i, j] := 1 - (o[i, 0]*o[i, 0])
          else
            Result[i, j] := 0;
        end;
    end;

end;

class function TMyMatrixOperations.KronMatrix(M1, M2: TMatrix): TMatrix;
var
  tmp : TMatrix ;
  i,j,
  k,l : Integer ;
  tc,tl : Integer ;
begin

  tmp := TMatrix.Create ( M1.RowCount * M2.RowCount , M1.ColCount * M2.ColCount );

  tc  := 0 ;
  tl  := 0 ;
  for i := 0  to M1.RowCount - 1 do
  begin

    for j := 0 to M2.RowCount - 1 do
    begin

      for k := 0 to M1.ColCount - 1 do
      begin

        for l := 0 to M2.ColCount - 1 do
        begin

          tmp[tl,tc] := M1[i,k] * M2[j,l] ;
          Inc(tc);

        end;

      end;
      Inc(tl);
      tc := 0 ;

    end;

  end;

  Result := tmp ;
end;

class function TMyMatrixOperations.MultiplyMatrix(M1,
  M2: TMatrix): TMatrix;
var
  tmp       : TMatrix ;
  i,j,k     : Integer ;
begin

  tmp := TMatrix.Create ( M1.FRow , M2.FCol );

  for i := 0 to M1.RowCount - 1 do
  begin
    for j := 0 to M2.ColCount - 1 do
    begin
      for k := 0 to M1.ColCount - 1 do
      begin
        tmp[i,j] := tmp[i,j] + ( M1[i,k] * M2[k,j] ) ;
      end;
    end;
  end;

  Result := tmp ;
end;

class function TMyMatrixOperations.TransposeMatrix(M1: TMatrix): TMatrix;
var
  tmp   : TMatrix ;
  i,j   : Integer ;
begin

  tmp := TMatrix.Create ( M1.ColCount , M1.RowCount );

  for i := 0  to tmp.RowCount -1 do
  begin
    for j := 0 to tmp.ColCount - 1 do
    begin
      tmp[i,j] := M1[j,i] ;
    end;
  end;
  Result := tmp ;
end;

end.
 